package cn.congine.wizarpos.mall.action;

import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import cn.congine.wizarpos.mall.model.open.AccessTokenInput;
import cn.congine.wizarpos.mall.model.open.CommonResultOutput;
import cn.congine.wizarpos.mall.model.open.MerchantDef;
import cn.congine.wizarpos.mall.model.open.MerchantDefQueryInput;
import cn.congine.wizarpos.mall.model.open.MerchantDefQueryOutput;
import cn.congine.wizarpos.mall.model.open.ShopTranLogInput;
import cn.congine.wizarpos.mall.model.open.ShopTranLogOutput;
import cn.congine.wizarpos.mall.model.open.TicketAddDetailInput;
import cn.congine.wizarpos.mall.model.open.TicketAddDetailOutput;
import cn.congine.wizarpos.mall.model.open.TicketBindingInput;
import cn.congine.wizarpos.mall.model.open.TicketBindingOutput;
import cn.congine.wizarpos.mall.model.open.TicketListInput;
import cn.congine.wizarpos.mall.model.open.TicketListOutput;
import cn.congine.wizarpos.mall.model.open.TicketToPackageInput;
import cn.congine.wizarpos.mall.model.open.TicketToPackageOutput;
import cn.congine.wizarpos.mall.model.open.TicketUseLog;
import cn.congine.wizarpos.mall.model.open.TicketUseLogInput;
import cn.congine.wizarpos.mall.model.open.TicketUseLogOutput;
import cn.congine.wizarpos.mall.model.open.TranLogView;
import cn.congine.wizarpos.mall.service.impl.WPosHttpClient;
import cn.congine.wizarpos.mall.service.impl.WizarposOpenRestClient;
import cn.congine.wizarpos.mall.utils.MatrixToImageWriter;
import cn.congine.wizarpos.mall.utils.SysConstants;
import cn.congine.wizarpos.mall.utils.Utils;
import cn.congine.wizarpos.mall.utils.WxSignUtil;
import cn.congine.wizarpos.mall.vo.Record;
import cn.congine.wizarpos.mall.vo.Ticket;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

@Controller
@RequestMapping(value = "/vip")
public class CardAction {
	private final Log log = LogFactory.getLog(getClass());

	@Autowired
	private WPosHttpClient wposHttpClient;

	@Resource(name = "messageSource")
	private MessageSource messageSource;

	@Autowired
	private WizarposOpenRestClient wizarposOpenRestClient;
	
	/**
	 * 会员卡展示页面
	 * 
	 * @param openId
	 * @param mid
	 * @return
	 */
	@RequestMapping(value = "/vip_card")
	public ModelAndView vipCard(
			@RequestParam(value = "mid", required = true) String mid,
			@RequestParam(value = "openId", required = true) String openId,RedirectAttributes attributes) {
		log.debug("vip_card--------------------");
		log.debug("openId =" + openId);
		log.debug("mid =" + mid);

		Map<String, Object> data = new HashMap<String, Object>();
		data.put("openId", openId);
		data.put("mid", mid);
		data.put("error_msg", "");
	
		// 商户数据
		MerchantDefQueryInput input = new MerchantDefQueryInput();
		input.setMid(mid);
		MerchantDefQueryOutput output = (MerchantDefQueryOutput) wizarposOpenRestClient.post(input, "/merchantdef/info", MerchantDefQueryOutput.class);		
		if (output == null || !SysConstants.OPEN_SUCCESS.equals(output.getCode())) {
			data.put("error_msg", SysConstants.NO_MERCHANT);
			return new ModelAndView("card/error",data);
		} else {
			MerchantDef merchantDef = output.getResult();
			//会员卡面默认值处理
			String vipImage = merchantDef.getVipImage();
			if (StringUtils.isEmpty(vipImage)) {
				merchantDef.setVipImage(SysConstants.DEFAULT_VIP_IMAGE);
			}
			data.put("merchantDef", merchantDef);
		}
		
		try {
			// 查询会员卡
			JSONObject result = wposHttpClient.getMerchantCardByOpenId(openId, mid);
			int code = result.getIntValue("code");
			log.debug("code =" + code);
			log.debug("msg =" + result.getString("msg"));

			if (code == SysConstants.NOCARD) {
				return new ModelAndView("card/receive_card", data);
			} else if (code == SysConstants.SUCCESS) {
				JSONObject card = result.getJSONObject("result");
				data.put("card_no", card.getString("cardNo"));
				data.put("mid", mid);
				data.put("balance", Utils.changF2Y(card.getIntValue("balance")));
				data.put(
						"points",
						card.getString("points") == null ? 0 : card
								.getString("points"));
				Map<String, Object> res = queryTicketForCard(mid, openId);
				data.put("ticket_counts", res.get("ticketCounts"));
				data.put("ticket_list", res.get("ticket_list"));
				
				attributes.addFlashAttribute("data",data);
				return new ModelAndView("redirect:/vip/vipCardView");
			} else {
				data.put("error_msg", result.getString("msg"));
			}
		} catch (Exception e) {
			log.error(e);
			data.put("error_msg", e.getMessage());
		}
		return new ModelAndView("card/error", data);
	}

	/**
	 * 会员卡注册信息录入页面
	 * 
	 * @param openId
	 * @param mid
	 * @return
	 */
	@RequestMapping(value = "/input_card")
	public ModelAndView inputCard(
			@RequestParam(value = "openId", required = true) String openId,
			@RequestParam(value = "mid", required = true) String mid,RedirectAttributes attributes) {
		log.debug("input_card--------------------");
		log.debug("openId =" + openId);
		log.debug("mid =" + mid);

		Map<String, Object> data = new HashMap<String, Object>();
		data.put("openId", openId);
		data.put("mid", mid);
		data.put("error_msg", "");

		try {
			JSONObject result = wposHttpClient.getMerchantCardByOpenId(openId, mid);

			int code = result.getIntValue("code");
			log.debug("code =" + code);
			log.debug("msg =" + result.getString("msg"));

			if (code == SysConstants.NOCARD) {
				attributes.addFlashAttribute("data",data);
				return new ModelAndView("redirect:/vip/inputCardView");
			} else if (code == SysConstants.SUCCESS) {
				JSONObject card = result.getJSONObject("result");
				data.put("card_no", card.getString("cardNo"));
				data.put("points", card.getString("points"));
				data.put("balance", Utils.changF2Y(card.getIntValue("balance")));
				Map<String, Object> res = queryTicketForCard(mid, openId);
				data.put("ticket_counts", res.get("ticketCounts"));
				data.put("ticket_list", res.get("ticket_list"));
				attributes.addFlashAttribute("data",data);
				return new ModelAndView("redirect:/vip/vipCardView");
			} else {
				data.put("error_msg", result.getString("msg"));
			}

		} catch (Exception e) {
			log.error(e);
			data.put("error_msg", e.getMessage());
		}
		return new ModelAndView("card/error", data);
	}

	/**
	 * 保存会员卡注册信息
	 * 
	 * @param openId
	 * @param mid
	 * @param name
	 * @param phone
	 * @return
	 */
	@RequestMapping(value = "/create_card")
	public ModelAndView createCard(
			@RequestParam(value = "openId", required = true) String openId,
			@RequestParam(value = "mid", required = true) String mid,
			@RequestParam(value = "name", required = false) String name,
			@RequestParam(value = "phone", required = false) String phone,RedirectAttributes attributes) {
		log.debug("create_card--------------------");
		log.debug("openId =" + openId);
		log.debug("mid =" + mid);
		log.debug("name =" + name);
		log.debug("phone =" + phone);

		Map<String, Object> data = new HashMap<String, Object>();
		data.put("mid", mid);
		data.put("openId", openId);
		data.put("name", name);
		data.put("phone", phone);

		try {
			JSONObject result = wposHttpClient.registerVipCard(openId, mid, URLDecoder.decode(name, "UTF-8"), phone);
			int code = result.getIntValue("code"); 
			log.debug("code =" + code);
			log.debug("msg =" + result.getString("msg"));

			if (code == SysConstants.SUCCESS) {
				JSONObject card = result.getJSONObject("result");
				data.put("card_no", card.getString("cardNo"));
				data.put("balance", Utils.changF2Y(card.getIntValue("balance")));
				data.put("points", card.getIntValue("points"));
				Map<String, Object> res = queryTicketForCard(mid, openId);
				data.put("ticket_counts", res.get("ticketCounts"));
				data.put("ticket_list", res.get("ticket_list"));

				// 商户数据
				MerchantDefQueryInput input = new MerchantDefQueryInput();
				input.setMid(mid);
				MerchantDefQueryOutput output = (MerchantDefQueryOutput) wizarposOpenRestClient.post(input, "/merchantdef/info", MerchantDefQueryOutput.class);		
				if (output == null || !SysConstants.OPEN_SUCCESS.equals(output.getCode())) {
					data.put("error_msg", SysConstants.NO_MERCHANT);
					return new ModelAndView("card/error",data);
				} else {
					MerchantDef merchantDef = output.getResult();
					data.put("merchantDef", merchantDef);
				}
				
				attributes.addFlashAttribute("data",data);
				return new ModelAndView("redirect:/vip/vipCardView");
			} else {
				data.put("error_msg", result.getString("msg"));
			}
		} catch (UnsupportedEncodingException e) {
			log.error(e.getMessage(), e);
			data.put("error_msg", e.getMessage());
		} catch (Exception e) {
			log.error(e);
			data.put("error_msg", e.getMessage());
		}
		
		return new ModelAndView("card/error", data);
	}
	
	@RequestMapping("/vipCardView")
	public ModelAndView vipCard()
	{
		return new ModelAndView("card/vip_card");
	}
	
	@RequestMapping("/inputCardView")
	public ModelAndView inputCardView()
	{
		return new ModelAndView("card/input_card");
	}

	/**
	 * 跳转到会员卡领取页面
	 * @param mid
	 * @param openId
	 * @return
	 * @author xudongdong
	 */
	@RequestMapping("/receiveCard")
	public ModelAndView receiveCard(@RequestParam(value = "mid", required = true) String mid,
			@RequestParam(value = "openId", required = true) String openId)
	{
		Map<String, Object> data = new HashMap<String, Object>();
		data.put("mid", mid);
		data.put("openId", openId);		
		return new ModelAndView("card/receive_card", data);
	}

	/**
	 * 查询电子券
	 * 
	 * @param openId
	 * @param mid
	 * @return
	 */
	private Map<String, Object> queryTicketForCard(String mid, String openId) {
		log.debug("queryTicket--------------------");
		List<Ticket> list = new ArrayList<Ticket>();
		Map<String, Object> resMap = new HashMap<String, Object>();
		int count = 0;
		try {
			JSONObject result = wposHttpClient.getMemberTicketInfo(openId, mid);
			int code = result.getIntValue("code");
			log.debug("code =" + code);
			log.debug("msg =" + result.getString("msg"));

			if (code == SysConstants.SUCCESS) {
				count = (int) result.getJSONObject("result").get("counts");
				JSONArray tickes = (JSONArray) result.getJSONObject("result")
						.get("tickets");
				log.debug(tickes.toJSONString());
				for (int i = 0; i < tickes.size(); i++) {
					JSONObject tick = (JSONObject) tickes.get(i);
					
					System.out.println("[ticket:]" + tick.toString());
					
					if (tick.isEmpty()) {
						continue;
					}
					Ticket ti = new Ticket(i);
					ti.setTicketName(tick.getString("ticket_name"));
					ti.setCounts(tick.getString("num"));
					ti.setBalance(tick.containsKey("balance")? tick.getString("balance") : "0");
					ti.setDesc(tick.getString("descn"));
					ti.setExpriyTime(tick.getString("expriy"));
					// 1 为微信券，要求微信券的card_id存在
					if ("1".equals(tick.getString("wxFlag")) && tick.containsKey("wx_code_id")) {
						ti.setWxFlag("1");
						ti.setWxCodeId(tick.getString("wx_code_id"));
					}
					
					List<String> tmpNoList = tick.containsKey("ticketNo") ? Arrays
							.asList(tick.getString("ticketNo").split(","))
							: new ArrayList<String>();
					List<String> tmpAddedList = tick.containsKey("wxAdded") ? Arrays
							.asList(tick.getString("wxAdded").split(","))
							: new ArrayList<String>();
							
					String added = "1";
					String ticketNo = null;
					for (int j = 0; j < tmpAddedList.size(); j++) {
						String addedTmp = tmpAddedList.get(j);
						if (addedTmp == null || addedTmp.equals("0")) {
							added = "0";
							ticketNo = tmpNoList.get(j);
							break;
						}
					}
					ti.setWxAdded(added);
					ti.setTicketNo(ticketNo);
					
					list.add(ti);
				}

				log.debug(list.size());
				resMap.put("ticketCounts", count);
				resMap.put("ticket_list", list);
			} else {
				resMap.put("ticketCounts", count);
				resMap.put("ticket_list", list);
				log.error(result.getString("msg"));
			}
		} catch (Exception e) {
			log.error(e);
		}
		return resMap;
	}

	/**
	 * 查询余额
	 * 
	 * @param openId
	 * @param mid
	 * @return
	 */
	@RequestMapping(value = "/query_balance")
	public ModelAndView queryBalance(
			@RequestParam(value = "openId", required = true) String openId,
			@RequestParam(value = "mid", required = true) String mid) {
		log.debug("query_balance--------------------");
		log.debug("openId =" + openId);
		log.debug("mid =" + mid);

		Map<String, Object> data = new HashMap<String, Object>();
		data.put("openId", openId);
		data.put("mid", mid);
		data.put("error_msg", "");
		
		try {
			JSONObject result = wposHttpClient.getMerchantCardByOpenId(openId, mid);
			int code = result.getIntValue("code");
			log.debug("code =" + code);
			log.debug("msg =" + result.getString("msg"));

			if (code == SysConstants.NOCARD) {
				return new ModelAndView("card/receive_card", data);
			} else if (code == SysConstants.SUCCESS) {
				JSONObject card = result.getJSONObject("result");
				data.put("card_no", card.getString("cardNo"));
				data.put("balance", Utils.changF2Y(card.getIntValue("balance")));
				return new ModelAndView("card/card_balance", data);
			} else {
				data.put("error_msg", result.getString("msg"));
			}

		} catch (Exception e) {
			log.error(e);
			data.put("error_msg", e.getMessage());
		}
		return new ModelAndView("card/error", data);
	}

	/**
	 * 查询积分
	 * 
	 * @param openId
	 * @param mid
	 * @return
	 */

	@RequestMapping(value = "/query_integral")
	public ModelAndView queryIntegral(
			@RequestParam(value = "openId", required = true) String openId,
			@RequestParam(value = "mid", required = true) String mid) {

		log.debug("query_integral--------------------");
		log.debug("openId =" + openId);
		log.debug("mid =" + mid);
		Map<String, Object> data = new HashMap<String, Object>();
		data.put("openId", openId);
		data.put("mid", mid);
		data.put("error_msg", "");
		
		try {
			JSONObject result = wposHttpClient.getMerchantCardByOpenId(openId, mid);
			int code = result.getIntValue("code");
			log.debug("code =" + code);
			log.debug("msg =" + result.getString("msg"));

			if (code == SysConstants.NOCARD) {
				return new ModelAndView("card/receive_card", data);
			} else if (code == SysConstants.SUCCESS) {
				JSONObject card = result.getJSONObject("result");
				data.put("card_no", card.getString("cardNo"));
				data.put("points", card.getIntValue("points"));
				return new ModelAndView("card/card_integral", data);
			} else {
				data.put("error_msg", result.getString("msg"));
			}

		} catch (Exception e) {
			log.error(e);
			data.put("error_msg", e.getMessage());
		}
		return new ModelAndView("card/error", data);
	}

	/**
	 * 交易记录查询
	 * @param openId
	 * @param mid
	 * @param tranType
	 * @param nextPage
	 * @return
	 * @author xudongdong
	 */
	@RequestMapping(value = "/get_record")
	@ResponseBody
	public List<TranLogView> getRecord(
			@RequestParam(value = "openId", required = true) String openId,
			@RequestParam(value = "mid", required = true) String mid,
			@RequestParam(value = "tranType", defaultValue = "1") String tranType,
			@RequestParam(value = "nextPage", defaultValue = "1") Integer nextPage) {

		ShopTranLogInput input = new ShopTranLogInput();
		input.setMid(mid);
		input.setOpenId(openId);
		input.setPageNo(nextPage.toString());
		ShopTranLogOutput output = (ShopTranLogOutput) wizarposOpenRestClient.post(input, "/wxshop/tran/log", ShopTranLogOutput.class);
		if (output != null) {
			return output.getResult();
		}
		return null;
	}
	
	/**
	 * 查询交易记录
	 * 
	 * @param openId
	 * @param mid
	 * @return
	 */
	@RequestMapping(value = "/query_record")
	public ModelAndView queryRecord(
			@RequestParam(value = "openId", required = true) String openId,
			@RequestParam(value = "mid", required = true) String mid) {
		log.debug("query_record--------------------");
		log.debug("openId =" + openId);
		log.debug("mid =" + mid);

		Map<String, Object> data = new HashMap<String, Object>();
		data.put("openId", openId);
		data.put("mid", mid);
		data.put("error_msg", "");

		try {
			JSONObject result = wposHttpClient.getMerchantCardByOpenId(openId, mid);
			int code = result.getIntValue("code");
			log.debug("code =" + code);
			log.debug("msg =" + result.getString("msg"));

			if (code == SysConstants.NOCARD) {
				return new ModelAndView("card/receive_card", data);
			} else if (code == SysConstants.SUCCESS) {
				// 查询余额
				data.put("balance", Utils.changF2Y(result.getJSONObject("result")
						.getIntValue("balance")));
				return new ModelAndView("card/card_record", data);
			} else {
				data.put("error_msg", result.getString("msg"));
			}

		} catch (Exception e) {
			log.error(e);
			data.put("error_msg", e.getMessage());
		}
		return new ModelAndView("card/error", data);
	}

	@SuppressWarnings("unused")
	private List<Record> processRecordArray(JSONArray record) {
		List<Record> list = new ArrayList<Record>();
		for (int i = 0; i < record.size(); i++) {
			Record re = new Record();
			re.setBalance(Utils.changF2Y(record.getJSONObject(i).getIntValue(
					"balance")));
			long tranTime = record.getJSONObject(i).getLongValue("tranTime");
			re.setTranTime(Utils.long2DateTimeString(tranTime));
			re.setTranType(record.getJSONObject(i).getString("tranType"));
			re.setAmount(Utils.changF2Y(record.getJSONObject(i).getIntValue(
					"amount")));
			list.add(re);
		}
		return list;
	}
	
	/**
	 * 获取受理码生成二维码
	 * 
	 * @param openId
	 * @param mid
	 * @param response
	 */
	@RequestMapping(value = "/get_qrcode")
	public void getQRcode(
			@RequestParam(value = "openId", required = true) String openId,
			@RequestParam(value = "mid", required = true) String mid,
			String random, HttpServletResponse response) {
		log.debug("get_qrcode---------------");
		log.info("生成code mid:" + mid);
		try {
			JSONObject result = wposHttpClient.getQRcodeTokenId(openId, mid);
			int code = result.getIntValue("code");
			log.debug("code =" + code);
			log.debug("msg =" + result.getString("msg"));

			if (code == SysConstants.SUCCESS) {
				JSONObject token = result.getJSONObject("result");
				String content = token.getString("tokenId");
				OutputStream stream = response.getOutputStream();
				MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
				Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>();
				hints.put(EncodeHintType.MARGIN, 1);
				hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
				// 容错率
				hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
				BitMatrix bitMatrix = multiFormatWriter.encode(content,
						BarcodeFormat.QR_CODE, 400, 400, hints);
				MatrixToImageWriter.writeToStream(bitMatrix, "png", stream);
			}
		} catch (Exception e) {
			log.error(e);
		}
	}

	/**
	 * 跳转到券列表页面
	 * 
	 * @param openId
	 * @param mid
	 * @return
	 * @throws Exception
	 * @author xudongdong
	 */
	@RequestMapping(value = "/ticket_list")
	public ModelAndView ticketList(
			@RequestParam(value = "openId", required = true) String openId,
			@RequestParam(value = "mid", required = true) String mid,
			HttpServletRequest httpRequest) throws Exception {	
		Map<String, Object> data = new HashMap<String, Object>();
		data.put("openId", openId);
		data.put("mid", mid);
		
		MerchantDefQueryInput merchantDefQueryInput = new MerchantDefQueryInput();
		merchantDefQueryInput.setMid(mid);
		MerchantDefQueryOutput MerchantDefouptut = (MerchantDefQueryOutput) wizarposOpenRestClient.post(merchantDefQueryInput, "/merchantdef/info", MerchantDefQueryOutput.class);
		if (MerchantDefouptut == null ) {
			return new ModelAndView("card/error").addObject("error_msg", "系统错误");
		}
		//非法慧商户号
		if ("60001".equals(MerchantDefouptut.getCode())) {
			data.put("error_msg", SysConstants.NO_MERCHANT);
			return new ModelAndView("card/error", data);
		}
		
		MerchantDef merchantDef = MerchantDefouptut.getResult();
		//非法慧商户号
		if (merchantDef == null) {
			data.put("error_msg", SysConstants.NO_MERCHANT);
			return new ModelAndView("card/error", data);
		}
		data.put("marchantName", merchantDef.getMerchantName());
		data.put("logoImage", merchantDef.getLogoImage());
		
		
		
		Map<String, Object> res = queryTicketForCard(mid, openId);
		data.put("ticket_counts", res.get("ticketCounts"));
		data.put("ticket_list", res.get("ticket_list"));
		
//		TicketListInput input = new TicketListInput();
//		input.setMid(mid);
//		input.setOpenId(openId);
//		
//
//		
//		TicketListOutput output = (TicketListOutput) wizarposOpenRestClient.post(input, "/wechart/ticket_list", TicketListOutput.class);
//		
//		data.put("ticket_counts", output.getNum());
//		data.put("ticket_list", output.getTicketList());

		return new ModelAndView("card/ticket_list", data);
	}
	
	
	
	/**
	 * 领取券的记录
	 * @param mid
	 * @param openId
	 * @param nextPage
	 * @return
	 * @author xudongdong
	 */
	@RequestMapping(value = "/get_ticket")
	@ResponseBody
	public List<Object> getTicket(
			@RequestParam(value = "mid", required = true) String mid,
			@RequestParam(value = "openId", required = true) String openId,
			@RequestParam(value = "nextPage", defaultValue = "1") String nextPage) {
		TicketAddDetailInput input = new TicketAddDetailInput();
		input.setMid(mid);
		input.setOpenId(openId);
		input.setPageNo(nextPage);
		TicketAddDetailOutput output = (TicketAddDetailOutput) wizarposOpenRestClient.post(input, "/wechart/ticket/add/detail", TicketAddDetailOutput.class);		
		if (output != null) {
			return output.getTicketInfoList();
		}
		return null;
	}
	
	/**
	 * 券的使用记录
	 * 
	 * @param mid
	 * @param openId
	 * @param nextPage
	 * @return
	 * @author xudongdong
	 */
	@RequestMapping(value = "/get_used_ticket")
	public 	@ResponseBody List<TicketUseLog> get_used_ticket(
			@RequestParam(value = "mid", required = true) String mid,
			@RequestParam(value = "openId", required = true) String openId,
			@RequestParam(value = "nextPage", defaultValue = "1") String nextPage) {
		
		TicketUseLogInput input = new TicketUseLogInput();
		input.setMid(mid);
		input.setOpenId(openId);
		input.setPageNo(nextPage);
		TicketUseLogOutput output = (TicketUseLogOutput) wizarposOpenRestClient.post(input, "/wxshop/ticket/use/log", TicketUseLogOutput.class);		
		if (output != null) {
			return output.getResult();
		}
		return null;		
	}	

	protected String getMid(String mid) {
		StringBuffer buffer = new StringBuffer();
		StringBuffer buffer1 = new StringBuffer();
		String middle = mid.substring(1, 3);
		char pre = mid.charAt(0);
		String aa = mid.substring(4);
		for (int i = 0; i <= 7 - aa.length(); i++) {
			buffer1.append("0");
		}
		buffer.append("100").append(pre).append("0").append(middle)
				.append(buffer1).append(aa);
		return buffer.toString();
	}

	/**
	 * 券修改 微信券添加到卡包时
	 * @param wxCardId
	 * @param ticketNo
	 * @param openId
	 * @param mid
	 * @param httpRequest
	 * @return
	 * @author xudongdong
	 */
	@RequestMapping(value = "/flag_ticket")
	@ResponseBody
	public ModelAndView flagTicket(
			@RequestParam(value = "wxCardId", required = true) String wxCardId,
			@RequestParam(value = "ticketNo", required = true) String ticketNo,
			@RequestParam(value = "openId", required = true) String openId,
			@RequestParam(value = "mid", required = true) String mid,
			HttpServletRequest httpRequest) {
		TicketToPackageInput input = new TicketToPackageInput();
		input.setMid(mid);
		input.setOpenId(openId);
		input.setWxCardId(wxCardId);
		input.setTicketNo(ticketNo);
		TicketToPackageOutput output = (TicketToPackageOutput) wizarposOpenRestClient.post(input, "/wechart/ticket/topackage", TicketToPackageOutput.class);						
		return new ModelAndView("forward:vip_card");
	}

	/**
	 * 绑定非会员卡
	 * 
	 * @param ticketNo
	 * @param openId
	 * @param mid
	 * @return
	 */
	@RequestMapping(value = "/binding")
	public @ResponseBody String binding(
			@RequestParam(value = "ticketNo", required = true) String ticketNo,
			@RequestParam(value = "openId", required = true) String openId,
			@RequestParam(value = "mid", required = true) String mid) {		
 		TicketBindingInput input = new TicketBindingInput();
		input.setMid(mid);
		input.setOpenId(openId);
		input.setTicketNo(ticketNo);
		TicketBindingOutput output = (TicketBindingOutput) wizarposOpenRestClient.post(input, "/wechart/ticket/banding", TicketBindingOutput.class);
		String code = output.getCode();
		if ("60011".equals(code)) {  //未知的卡券
			return "1";
		} else if ("60036".equals(code)) {  //卡券已被绑定
			return "2";
		} else {  //绑定成功
			return "0";
		}		
	}
	
	/**
	 * 进入绑定非会员卡页
	 * 
	 * @param ticketNo
	 * @param openId
	 * @param mid
	 * @return
	 * @throws Exception
	 */
	@RequestMapping(value = "/tobinding")
	public ModelAndView toBinding(
			@RequestParam(value = "openId", required = true) String openId,
			@RequestParam(value = "mid", required = true) String mid,
			HttpServletRequest httpRequest) throws Exception {
		Map<String, Object> data = new HashMap<String, Object>();
		data.put("mid", mid);
		data.put("openId", openId);
		
		// 请求微信 js api的完整页面地址
		String baseUrl = getBaseURL(httpRequest);
		StringBuffer tmpUrl = new StringBuffer();
		tmpUrl.append(baseUrl);
		tmpUrl.append("/vip/tobinding");
		tmpUrl.append("?mid=").append(mid);
		tmpUrl.append("&openId=").append(openId);
		String url = tmpUrl.toString();
		
		// 请求微信api的ticket
		AccessTokenInput jsInput = new AccessTokenInput();
		jsInput.setMid(mid);
		CommonResultOutput jsOutput = (CommonResultOutput) wizarposOpenRestClient.post(jsInput, "/weixin/ticket/js", CommonResultOutput.class);		
		if (jsOutput == null || SysConstants.OPEN_ERROR.equals(jsOutput.getCode())) {
			return new ModelAndView("error").addObject("err_message",
					SysConstants.OPEN_ERROR);
		} else if (SysConstants.NO_MERCHANT_CODE.equals(jsOutput.getCode())) {
			return new ModelAndView("error").addObject("err_message",
					SysConstants.NO_MERCHANT);
		} else {
			Map<String, String> result = (Map<String, String>) jsOutput.getResult();
			String jsTicket = result.get("ticket");
			String appid = result.get("appid");
			data.put("appId", appid);
			Map<String, String> ret = WxSignUtil.commonSign(jsTicket, url,
					WxSignUtil.createTimestamp());
			data.putAll(ret);
		}
		
		return new ModelAndView("card/binding", data);
	}
	
	private String getBaseURL(HttpServletRequest httpRequest) {
		String baseUrl = "http://"
				+ messageSource.getMessage(SysConstants.SERVICE_DNS, null,
						Locale.ENGLISH);
		baseUrl += httpRequest.getSession().getServletContext().getContextPath();
		return baseUrl;
	}
}
